palainp / mirage-sshfs

ISC License
22 stars 1 forks source link

Write fails with hvt #4

Closed palainp closed 2 years ago

palainp commented 2 years ago

All commands involving a write operation to disk with hvt seem to be stuck. To reproduce:

mirage configure -t hvt && make depend && make && \
solo5-hvt --net:service=tap100 --block:storage=disk.img mirage_sshfs.hvt -l debug --port 22022 --user mirage

In another terminal:

sshfs mirage@10.0.0.2:/ /mount/ -p 22022 -o IdentityFile=/pathto/mirage && \
ls /mount/ # is ok
cat /mount/mirage.pub # is ok
mkdir /mount/tmp # is ko
touch /mount/test # is ko
echo ok > /mount/bla # is ko
hannesm commented 2 years ago

my intuition is that we may be in the case of https://github.com/mirage/mirage-block-solo5/blob/master/src/block.ml#L86-L90 with the fat filesystem -- i.e. I'd suggest to do some printf debugging in mirage-block-solo5 checking what buffer sizes are passed.

palainp commented 2 years ago

Update: I'm not sure mirage-block-solo5 is guilty here. I must have a wrong usage of the redefined bind: EDIT: it was, as well as my (>>*=) definition

  let (>>*=) m f = m >>= function
    | Error e -> fail "%a" FS.pp_write_error (e :> FS.write_error)
    | Ok x    -> f x

When I modify a "fat alterer call", for example:

FS.destroy root path >>*= fun () -> 

into:

FS.destroy root path >>= fun _ -> 

It does not freeze anymore (but sadly does not update the filesystem, I still have an eye on mirage-block-solo5 :) ). And regarding the "not alterer calls" (that may return a value, as for FS.size or FS.read) I can still use the >>*= fun(value) -> mnemonic.

palainp commented 2 years ago

Ok, using FS.create root path >>= fun _ -> instead of FS.create root path >>*= fun () -> only discards the error which was, in my example when I try to create an empty file, a block read error. The pretty print for errors does not seems to be correct in my code :/ So your intuition was perfectly correct and I must now investigate deeply what is going on here.

palainp commented 2 years ago

So far what I can observe is when we need to write to the fat16 partition, a number of 512 bytes long reads are done, and after that it fails when it tries to read a 4096 bytes long page with a SOLO5_R_EINVAL invalid_argument error.

The 4096 size is a constant in the write_update function, and if we change the 4096 bytes page size in https://github.com/mirage/ocaml-fat/blob/9171848e47a57a4b2bc1a72386abc82779876ae4/src/fat.ml#L134 to a 512 bytes, the write update finish correctly (but I use some small files for my current tests).

The 1 block limit is defined in https://github.com/Solo5/solo5/blob/0eb8cb8f57943e7872a94e19695911a1e0b8aef6/bindings/hvt/block.c#L39-L42 because some targets that lacks multisector read or write. I think it is possible to adapt around the l134 of fat.ml to read 8 sectors and overwrite them properly to deal with that 1 block limit.

palainp commented 2 years ago

Using the new chamelon fs layer, this issue is no longer present.