vnop_advlock not being called for my filesystem

When running AJA System Test for my custom filesystem, the write and read tests get stuck intermittently.

I didn't observe any error codes being returned by my vnop_read/write or sock_receive/send functions.

Dtrace(1)'ing the vnops being called by AJA System Test for smbfs revealed that amongst other things vnop_advlock is being called:

  0    -> smbfs_vnop_advlock                  ajasystemtest -> smbfs_vnop_advlock(ajatest.dat, op: 0x2, fl->l_start: 0, fl->l_len: 0, fl->l_pid: 0, fl->l_type: 2, fl->l_whence: 0, flags: 0x40, timeout: 0)
  0    <- smbfs_vnop_advlock                  ajasystemtest -> smbfs_vnop_advlock(ajatest.dat) -> -1934627947504

op: 0x2
#define F_SETFD         2               /* set file descriptor flags */

fl->l_len: 0 ;len = 0 means until end of file
fl->l_type: 2 ;#define F_UNLCK         2               /* unlock */
fl->l_whence: 0 ;#define SEEK_SET        0       /* set file offset to offset */

flags: 0x40 ;#define F_POSIX         0x040           /* Use POSIX semantics for lock */

As my filesystem didn't implement vnop_advlock, I thought I'd explore that avenue.

My vnop_advlock simply returns KERN_SUCCESS.

Both f_capabilities.valid and f_capabilities.capabilities of struct vfs_attr have VOL_CAP_INT_ADVLOCK and VOL_CAP_INT_FLOCK set.

Yet, vnop_advlock doesn't get called for my filesystem when running AJA System Test.

Any tips on what could be amiss there would be much appreciated.

Answered by DTS Engineer in 800826022

I disabled local locking and implemented a vnop_advlock of my own.

As a quick side not, keep in mind that POSIX locking is not widely used on macOS. There may be other reasons why this support is important to you, but you should not expect this to provide "general" protection against write collisions. macOS apps simply don't really use this mechanism.

AJAsystemtest issues a POSIX advlock request with vnop_advlock_args.a_flags being set to F_POSIX.

Have you written your own test and/or do you have the source to the test(s) you're using? The first step here it so make sure you understand exactly what the client did before you assume that there is any actually "issue" at work here. To put that another way, what you're reporting here is basically a "user level issue" ("my app doesn't work"), not an actual software problem ("this particular function is not behaving the way I'd expect").

Part of your basic development process here needs to be a complete set of tests tools/apps that specifically test every single operation your file system supports. Often these eventually become unit tests used to ensure ongoing correctness, but in the initial development process they're simply the basic tool you use to ensure your file system actually does what you think it should.

What I don't understand is why I'm only getting F_UNLCKs, but no F_SETLKs.

Please refer to the POSIX specification:

https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html

Quick summary, "F_UNLCK" and "F_SETLK" are not "peer" operations. F_UNLCK is a lock type, while F_SETLK is used to modify the lock state. In terms of what "AJAsystemtest" is actually doing, my guess is that they're simply checking the lock state but not taking the lock themselves but that's only a guess. My actual answer is that apps do all sorts of odd nonsense with the file system, which is why you need to write your own tests.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

My vnop_advlock simply returns KERN_SUCCESS.

Both f_capabilities.valid and f_capabilities.capabilities of struct vfs_attr have VOL_CAP_INT_ADVLOCK and VOL_CAP_INT_FLOCK set.

As a general comment, claiming you support an operation don't support and returning KERN_SUCCESS on an operation you did not do is poor idea.

As my filesystem didn't implement vnop_advlock, I thought I'd explore that avenue.

Any operation you do not support should be handled by the "err_" ("err_advlock") stub functions. That's why those functions exist.

Yet, vnop_advlock doesn't get called for my filesystem when running AJA System Test.

Most (all?) of our local file systems (including, HFS+ and APFS) don't directly implement file locking. The vfs layer has it's own locking implementation which a VFS driver can enable on the mount point by calling "vfs_setlocklocal", in which case "vnop_advlock" will not be called.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thanks for a prompt response.

I disabled local locking and implemented a vnop_advlock of my own.

AJAsystemtest issues a POSIX advlock request with vnop_advlock_args.a_flags being set to F_POSIX.

What I don't understand is why I'm only getting F_UNLCKs, but no F_SETLKs.

A little help clarifying why this is, as well as being pointed in the right direction would be much appreciated.

Accepted Answer

I disabled local locking and implemented a vnop_advlock of my own.

As a quick side not, keep in mind that POSIX locking is not widely used on macOS. There may be other reasons why this support is important to you, but you should not expect this to provide "general" protection against write collisions. macOS apps simply don't really use this mechanism.

AJAsystemtest issues a POSIX advlock request with vnop_advlock_args.a_flags being set to F_POSIX.

Have you written your own test and/or do you have the source to the test(s) you're using? The first step here it so make sure you understand exactly what the client did before you assume that there is any actually "issue" at work here. To put that another way, what you're reporting here is basically a "user level issue" ("my app doesn't work"), not an actual software problem ("this particular function is not behaving the way I'd expect").

Part of your basic development process here needs to be a complete set of tests tools/apps that specifically test every single operation your file system supports. Often these eventually become unit tests used to ensure ongoing correctness, but in the initial development process they're simply the basic tool you use to ensure your file system actually does what you think it should.

What I don't understand is why I'm only getting F_UNLCKs, but no F_SETLKs.

Please refer to the POSIX specification:

https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html

Quick summary, "F_UNLCK" and "F_SETLK" are not "peer" operations. F_UNLCK is a lock type, while F_SETLK is used to modify the lock state. In terms of what "AJAsystemtest" is actually doing, my guess is that they're simply checking the lock state but not taking the lock themselves but that's only a guess. My actual answer is that apps do all sorts of odd nonsense with the file system, which is why you need to write your own tests.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thanks very much for clarifying things, Kevin.

Coincidentally, I too was thinking of writing my own tests for the VNOPs implemented.

Alexander Kapshuk

vnop_advlock not being called for my filesystem
 
 
Q