• NeilBrown's avatar
    NFS: add barriers when testing for NFS_FSDATA_BLOCKED · 99bc9f2e
    NeilBrown authored
    dentry->d_fsdata is set to NFS_FSDATA_BLOCKED while unlinking or
    renaming-over a file to ensure that no open succeeds while the NFS
    operation progressed on the server.
    
    Setting dentry->d_fsdata to NFS_FSDATA_BLOCKED is done under ->d_lock
    after checking the refcount is not elevated.  Any attempt to open the
    file (through that name) will go through lookp_open() which will take
    ->d_lock while incrementing the refcount, we can be sure that once the
    new value is set, __nfs_lookup_revalidate() *will* see the new value and
    will block.
    
    We don't have any locking guarantee that when we set ->d_fsdata to NULL,
    the wait_var_event() in __nfs_lookup_revalidate() will notice.
    wait/wake primitives do NOT provide barriers to guarantee order.  We
    must use smp_load_acquire() in wait_var_event() to ensure we look at an
    up-to-date value, and must use smp_store_release() before wake_up_var().
    
    This patch adds those barrier functions and factors out
    block_revalidate() and unblock_revalidate() far clarity.
    
    There is also a hypothetical bug in that if memory allocation fails
    (which never happens in practice) we might leave ->d_fsdata locked.
    This patch adds the missing call to unblock_revalidate().
    Reported-and-tested-by: default avatarRichard Kojedzinszky <richard+debian+bugreport@kojedz.in>
    Closes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1071501
    Fixes: 3c59366c ("NFS: don't unhash dentry during unlink/rename")
    Signed-off-by: default avatarNeilBrown <neilb@suse.de>
    Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
    99bc9f2e
dir.c 87.3 KB