LINUX: Return errors in our d_revalidate 17/14417/2
authorAndrew Deason <adeason@sinenomine.net>
Mon, 26 Oct 2020 17:35:32 +0000 (12:35 -0500)
committerBenjamin Kaduk <kaduk@mit.edu>
Fri, 27 Nov 2020 18:15:41 +0000 (13:15 -0500)
commit78e5e1b0e54b31bb08b7578e86a6a2a95770d94c
tree71e292459b7362813c4df01a35f7ec46d0a0fa28
parent4c33820525af510a8a937289005e39d5b6683b19
LINUX: Return errors in our d_revalidate

In our d_revalidate callback (afs_linux_dentry_revalidate), we
currently 'goto bad_dentry' when we encounter any error. This can
happen if we can't allocate memory or some other internal errors, or
if the relevant afs_lookup call fails just due to plain network
errors.

For any of these cases, we'll treat the dentry as if it's no longer
valid, so we'll return '0' and call d_invalidate() on the dentry.
However, the behavior of d_invalidate changed, as mentioned in commit
afbc199f1 (LINUX: Avoid d_invalidate() during
afs_ShakeLooseVCaches()). After a certain point in the Linux kernel,
d_invalidate() will also effectively d_drop() the given dentry,
unhashing it. This can cause getcwd() calls to fail with ENOENT for
those directories (as mentioned in afbc199f1), and can cause
bind-mount calls to fail similarly during a small window.

To avoid all of this, when we encounter an error that prevents us from
checking if the dentry is valid or not, we need to return an error,
instead of saying 'yes' or 'no'. So, change
afs_linux_dentry_revalidate to jump to the 'done' label when we
encounter such errors, and avoid calling d_drop/d_invalidate in such
cases. This also lets us remove the 'lookup_good' variable and
consolidate some of the related logic.

Important note: in older Linux kernels, d_revalidate cannot return
errors; callers just interpreted its return value as either 'valid'
(non-zero) or 'not valid' (zero). The treatment of negative values as
errors was introduced in Linux commit
bcdc5e019d9f525a9f181a7de642d3a9c27c7610, which was included in
2.6.19. This is very old, but technically still above our stated
requirements for the Linux kernel, so try to handle this case, by
jumping to 'bad_dentry' still for those old kernels. Just do this with
a version check, since no configure check can detect this (no function
signatures changed), and the only Linux versions that are a concern
are quite old.

Change-Id: Ie530ce08463cf6b6899f056cb76ae4047c989ef2
Reviewed-on: https://gerrit.openafs.org/14417
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
src/afs/LINUX/osi_vnodeops.c