Truncate?
delehef opened this issue · 4 comments
I'm currently using fuse-rs
(0.4.0-dev) to implement a rather trivial FS. Read-only is working as a charm, but I'm tripping over an issue if I make my virtual files writeable.
When editing then saving one with vim for instance, appending works perfectly fine: vim's call to write
asks for a write to a buffer that runs after the end of the file, I extend it and write, done. But when removing stuff however, vim (according to strace) first calls a ftruncate
on the file, to which fuse-rs
returns an ENOSYS
/not implemented, then rewrite the whole content. But as I can't know which parts of it were removed, I can't fit the file to the right size, and thus I end up with a file with overflow garbage at the end.
In another example, when doing the same with strace + vi, instead of doing a ftruncate
+ write
, it calls open
with the O_TRUNC
flag. According to there (end of the page), FUSE kernel module automatically calls a truncate
, that is still ENOSYS
, and thus vi's save fail with a Function not implemented
.
As mentioned in the previous link, I also tried to pass -o atomic_o_trunc
flag to fuse, but if the other ones (-o autounmount
and -o nonempty
) works perfectly fine, this one seems to be ignored (strace shows the same calls to ftruncate
).
So in the end, am I making a stupid mistake I can't find somewhere, or maybe is there a reason I missed for which truncate
is not implemented?
truncate
is one of the many things that FUSE sends to the filesystem as part of the setattr
syscall. If you get a setattr
and the size
argument is not None
, that's a truncate
call.
And here I was, naively thinking that syscalls and FUSE operations mapped one-to-one...
Thanks a lot, and sorry for the bother.
No worries, it's certainly not very unintuitive.
As an aside, I have a crate, fuse-mt
which is a wrapper around this one and which tries to make FUSE filesystems a bit easier to implement, among other things by splitting the getattr
function into several which match the original syscalls better. See https://github.com/wfraser/fuse-mt/blob/f81f0eb77f1f5f5ebd6de819f5a1a79e7089b3e3/src/fusemt.rs#L142 where it does this. It also adds inode->path translation and some multi-threading around read/write as well. Just an alternative to consider.
The MT would prove very useful in my particular case; and the path-only system is the icing on the cake. I'll probably switch to it as soon as fuse-rs
0.4 is published and fuse-mt
switched to it, thanks for the head-up!