Can I just use std::fs normally, would async make a difference at all ? I don't have any concrete performance requirements or anything, but I'm planing on working with a shared volume soon and was wondering if there is any noticeable characteristics I should look out for.
The whole design intention of NFS is that clients interact with it using normal IO system calls - open etc - exactly like they would a local filesystem. Operationally, that works surprisingly well when everything is going well, but for some surprise latency, though it does have limitations that some kinds of software need to consider.
If your program does not use filesystem locks, then you can use normal FS interfaces. If it uses FS locks (of any kind), you'll need to take more care, and may need to set up additional services on your NFS server.
The thing to look out for is that a lot of software makes tacit assumptions about the return values of various FS calls - the classic one being the assumption that closing a file handle cannot fail (it can). Rust helps here as most things that interact with the FS have #[must_use] return values, but you'll want to take care there as well.
NFS does not support the full gamut of filesystem operations (e.g. mmap doesn't magically give you shared atomic memory between clients) and has a few weird behaviors like ESTALE. But it's still much closer to a real filesystem than things like s3fs for example.
You'll also want NFSv4 support on both client and server side.
And you'll want the network connection between the machines to be really reliable. Dealing with hangs due to the filesystem not being reachable is no fun.
Regarding performance, well... latency, IOPS and throughput are all bounded by both the network and the remote storage devices. So it'll generally perform worse than NVMe but not necessarily worse than local HDDs.
If you're operating on a lot of small files or doing small random reads/writes you'll want to throw multiple threads at the problem to mask latency.