OpenAFS Master Repository branch, master, updated. openafs-devel-1_9_1-265-g2b32b13

Gerrit Code Review gerrit@openafs.org
Fri, 12 May 2023 16:16:29 -0400


The following commit has been merged in the master branch:
commit 2b32b130f534068251ce9fd1b621de6e480d56d7
Author: Andrew Deason <adeason@sinenomine.net>
Date:   Fri May 5 16:47:45 2023 -0500

    LINUX: Set .getattr for symlinks
    
    On Linux, we can define a .getattr callback for files and directories,
    which is called when a caller requests metadata for the file, such as
    during lstat(). For regular files and directories, we set this to
    afs_linux_getattr(), which updates the metadata for the file in
    question if it's out of date (CStatd not set).
    
    For symlinks, however, we don't set .getattr at all. This would seem
    to allow symlink metadata to become stale if another client changes
    it, but the metadata often happens to stay up to date via other means.
    For example, we can see the following happen:
    
    - Another client changes, for example, the owner of a symlink we have
      cached.
    
    - The fileserver sends us a callback break, and so we clear CStatd for
      the vcache for the symlink.
    
    - lstat() is called for the symlink, which causes
      afs_linux_dentry_revalidate() to be called for the cached dentry.
      Since CStatd is not set for the vcache, we verify the entry by
      calling afs_lookup(), and then update the symlink's metadata via
      afs_getattr() and vattr2inode().
    
    However, if CStatd _is_ set for the symlink when lstat() is called,
    afs_linux_dentry_revalidate() will not update anything, and will just
    return success. So, if we manage to set CStatd for the symlink without
    updating it's Linux VFS metadata, the Linux metadata won't be updated,
    and we'll report the old metadata to the caller of lstat().
    
    We can set CStatd without updating the Linux VFS info in a few
    different ways. A few pioctls such as PRemoveMount or PFlushMount can
    do this if they encounter an error, but the only code paths that call
    these pioctls in OpenAFS (via the 'fs' utility) also lstat() the
    relevant path, so this doesn't happen in practice.
    
    A more common way that this can occur is via afs_DoBulkStat(). If
    userspace triggers a bulkstat that includes the symlink in question,
    the symlink would gain the CStatd flag without any interaction with
    the Linux VFS.
    
    For example, say a symlink was chown'd from 'adeason' to 'root'. On
    another client with the symlink cached, running 'ls -l' on the symlink
    itself would show the updated owner, because
    afs_linux_dentry_revalidate() updates the metadata:
    
        $ ls -l dir.slink
        lrwxr-xr-x. 1 root root       3 May  5 14:48 dir.slink -> dir
    
    But if we 'ls -l' the entire directory, which contains other entries,
    we will bulkstat many of the entries, possibly including the symlink.
    And so we may see the old metadata:
    
        $ ls -l
        total 9
        [...]
        lrwxr-xr-x. 1 adeason root       3 May  5 14:48 dir.slink -> dir
    
    Triggering this behavior requires a bulkstat to be triggered before we
    access the symlink itself, and so triggering this behavior depends on
    the order of the entries in the directory as well as whether the other
    items in the dir are cached. As such, triggering this behavior during
    normal operation tends to be inconsistent and confusing.
    
    The only lstat() info for symlinks that can change like this is the
    owner, group, and modtime; mode bits cannot change, and neither can
    the length/size (or the contents in general). So, stale metadata tends
    to not be very noticeable.
    
    To fix all of this, set .getattr to afs_linux_getattr() for symlinks,
    just like we do for regular files and directories. This ensures that
    we will update the Linux VFS metadata for the symlink when it is
    requested, so we won't return stale metadata to callers.
    
    This behavior appears to have existed for symlinks on Linux for quite
    a while, possibly since our Linux 2.6 support was added. The behavoir
    may have been introduced around commit b860b359d58
    (initial-linux24-support-20001105) or commit 00543744955
    (linux22-fix-20040405). Before those commits, we defined a .revalidate
    callback for symlinks, which was called on older Linux versions before
    fetching file metadata, and so probably ensured that an lstat() on a
    symlink returned properly updated info.
    
    Change-Id: I90d751e3175e24e9f9409cea6c079b097c78b51b
    Reviewed-on: https://gerrit.openafs.org/15423
    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 | 1 +
 1 file changed, 1 insertion(+)

-- 
OpenAFS Master Repository