AFAICT from man pages and documentation, a NFS client should invalidate its view of a directory if mtime of the directory changes. This makes sense as that attribute should change if a file is removed or added.
However the observed behaviour from the Linux kernel is that it completely ignores changes to mtime. You can observe mtime updating via stat calls from the client, but the client shows stale directory contents. This stale content is also permanent and not subject to any cache timeout.
What the client does look at instead is ctime. This distinction doesn't seem to matter much for Linux servers (all UNIX:y systems?) as both mtime and ctime are updated when a file is added or removed. However other systems do not have this behaviour, e.g. Windows that abuses the ctime for "creation time".
I'm having trouble following the cache system in the code, but from what I can tell nfs_lookup_revalidate_dentry() should decide if a refresh is needed. And it in turn expects nfs_refresh_inode() to make that call. And that seem to involve nfs_inode_attrs_need_update() which has a comment that it only looks at ctime.
This behaviour seems to have been around for ages, so we'll have to work around it in our end anyway. But I figured I'd at least inform you. :)
Sorry, but we will not be trying to fix Windows server bugs on the Linux client.
I'm confused. Are you're saying I've read the documentation wrong? Or the documentation is incorrect?
I.e. a server MUST update ctime if a file is added or removed and this is a valid assumption by the Linux NFS client?
I'm saying that RFC1813 does not allow servers to change the meaning of ctime. That kind of change will have repercussions on all attribute revalidation.
To quote from RFC1813:
In some cases, a server can support most of the semantics
described by the protocol but not all. For example, the ctime
field in the fattr structure gives the time that a file's
attributes were last modified. Many systems do not keep this
information. In this case, rather than not support the GETATTR
operation, a server could simulate it by returning the last
modified time in place of ctime. Servers must be careful when
simulating attribute information because of possible side
effects on clients.
In this case, if they are replacing the ctime with the birth time, they are not even trying to emulate the expected behaviour. We can't and we won't support that kind of abuse of the protocol.
Right, I'm not saying that responding with birth time in ctime is in any way sane. That is not really the issue here.
What I'm concerned about is that using ctime to determine if a directory needs to be re-checked seems off and that it should really be mtime a kernel looks at. RFC1813 doesn't seem to say much about when you can and cannot cache the contents of a directory unfortunately. But given that the files of a directory is it's "data", it seems wrong to look at ctime which would indicate changes in things like ownership of the directory itself. And I could not find any documentation clearly stating that ctime MUST change.
If the Windows server is fixed so that ctime represents the last time the ownership or permissions of the directory was changed, then the Linux server would still be unable to talk to that server. It would need to implement the same semantics as Linux, and I'd really like to be able to point to a source as to why that is. It would be much preferable to "/* Because the Linux kernel doesn't work otherwise */".
The reason for choosing the ctime is because that is the basis for most NFSv4 change attributes, and so it allows us to reuse the same code between NFSv2, NFSv3 and NFSv4.
Another issue is that mtime can be set directly by application, and is often reset by backup/restore programs after restoring a file or directory. In those cases we want to detect that the file/directory and its contents may have changed. That means checking the ctime anyway to ensure that mtime+ctime are indeed in sync.