Problem accessing cifs share on Mono application

I have a problem accessing a CIFS share over mono applications. I have reported the problem both in

Sonarr: File Browser does not show subdirectories - Help & Support - sonarr :: forums
Mono: http://mono.1490590.n4.nabble.com/Accessing-shared-file-system-td4670282.html#a4670285

This could turn out to be platform specific, so I post it here since some of us might be using the Vero4K for the same use case, just in case anybody can reproduce it or otherwise discard the hypothesis.

Thanks.

Vero 4K runs an armv7 userland which is quite common, I don’t think the issue will be specific to hardware

Sam

Ran this through the IRC channel of Mono and one user there ran the test application without issue. Just want to hear from someelse here.

It is enough to run the csharp console and test listing the contents of a cifs shared mount:

> csharp

csharp> using System
csharp> using System.IO
csharp> Directory.GetFileSystemEntries(@"<path>","*")

To install mono: apt install mono-complete

I will test this out on a i386 debian jessie.

I tested on amd64 debian Jessie (kernel 3.16.X) and it works.
I tested on Raspberry Pi 2B with OSMC (kernel 4.4.X) and it works.
On Vero4K (kernel 3.14.X) is not working.

Does look like a Vero4K specific issue.

What’s the output of the console above?

An array of strings, each being a full path of an element (dir or file) contained in the specified path (non recursive). On the Vero4K an empty array, on the others the files and dirs. Mounted the same share using the same procedure on all platforms.

Vero4K:

> ls /mnt/unsorted
test
> sudo csharp
csharp> using System.IO
csharp> Directory.GetFileSystemEntries(@"/mnt/unsorted","*")
{ } 

Working:

csharp> Directory.GetFileSystemEntries(@"/mnt/unsorted/","*")
{ "/mnt/unsorted/test" }

Hi

Unfortunately I’m not sure why this may be the case. Is GetFileSystemEntries working for any paths at all?

You could try using strace to see how Mono is trying to check the directory. If you can access the mountpoint via ls via bash, I suspect it’s not an OSMC issue.

What’s the ‘procedure’ for mounting?

Sam

Yes, it is working on local paths. I may test with other types of network mounts, unfortunately with my NAS I am tied to cifs.

Mount with

sudo mount.cifs //10.8.1.2/TC-Disk/Unsorted /mnt/unsorted -o user=admin

Of course I can operate with the mount normally afterwards, except with Mono.

I will look into strace.

This is the result of running the test on Vero4K with strace:

stat64("/mnt/unsorted", {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
lstat64("/mnt/unsorted", {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
geteuid32()                             = 0
openat(AT_FDCWD, "/mnt/unsorted", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 4
getdents(4, 0x1135b50, 32768)           = -1 EOVERFLOW (Value too large for defined data type)
close(4)                                = 0

The way I see it, it could be that the application is accessing 64 bit inode based filesystem using 32bit calls.

mono --version
Mono JIT compiler version 4.8.0 (Stable 4.8.0.520/8f6d0f6 Wed Mar 15 16:18:12 UTC 2017)
Copyright © 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
TLS: __thread
SIGSEGV: normal
Notifications: epoll
Architecture: armel,vfp+hard
Disabled: none
Misc: softdebug
LLVM: supported, not enabled.
GC: sgen

This explains why it would not happen in the other two scenarios. I will probably need to be running mono in 64 bits and not 32 bits, now where would I get that from.

mono-project.com provides arm64 packages. I wonder how compatible is that with aarch64.

Try setarch linux32 when calling csharp.

Have a look at http://www.tcm.phy.cam.ac.uk/sw/inodes64.html.

You could compile a lib and use LD_PRELOAD= when launching csharp to overload the three methods. Then it should work fine without a need to recompile Mono.

Sam

I will try that.

Towards a more definitive solution, would it be reasonable to try to compile mono for aarch64? Do you think arm64 would be compatible? Or is userland only 32 bits? Do you you have any tips towards cross compiling, maybe something setup?

sudo apt-get install aarch64-toolchain-osmc

will give you a compatible toolchain. OSMC can run most 32-bit and 64-bit binaries side-by-side on Vero 4K.

I’d try the Mono aarch64 build. It should work, but you may need to install some dependencies after. You could probably even just run:

sudo apt-get install mono:arm64

Sam

Well, one of the deps is asking me is for binutils:arm64 to replace binutils:armhf. I don’t know how to go about that, but probably is not going to end up well.

Probably best not to do that. The LD preload technique should do the job just fine

Cheers

Sam

LD_PRELOAD: it seems that the library is not enough, need to modify it to reroute the call of getdents to getdents64. I could do some trial and error at it, but I would actually be playing with my own data. My shortest path could actually be to recompile mono on armhf with large file system support, which should also get rid of the issue.

Yes – that’s probably the best way to do it.
I haven’t used Mono in many years, but if you need any pointers, please let me know.

Cheers

Sam

Found this in the man page of mount.cifs:

Inode Numbers

...
Note that the UniqueID is a different value from the server inode number. The UniqueID value is unique over the scope
of the entire server and is often greater than 2 power 32. This value often makes programs that are not compiled with
LFS (Large File Support), to trigger a glibc EOVERFLOW error as this won't fit in the target structure field. It is strongly
recommended to compile your programs with LFS support (i.e. with -D_FILE_OFFSET_BITS=64) to prevent this
problem. You can also use "noserverino" mount option to generate inode numbers smaller than 2 power 32 on the
client. But you may not be able to detect hardlinks properly.

Looks like another possible workaround.

1 Like