Fix afs_get_link() to take the validate_lock around afs_read_single() to prevent races between multiple ->get_link() calls. Fixes: eae9e78951bb ("afs: Use netfslib for symlinks, allowing them to be cached") Closes: https://sashiko.dev/#/patchset/20260326104544.509518-1-dhowells%40redhat.com Signed-off-by: David Howells cc: Marc Dionne cc: linux-afs@lists.infradead.org cc: linux-fsdevel@vger.kernel.org --- fs/afs/inode.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 06e25e1b12df..5207c4a003f6 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -78,10 +78,19 @@ const char *afs_get_link(struct dentry *dentry, struct inode *inode, goto good; fetch: - ret = afs_read_single(vnode, NULL); - if (ret < 0) - return ERR_PTR(ret); - set_bit(AFS_VNODE_DIR_READ, &vnode->flags); + if (down_write_killable(&vnode->validate_lock) < 0) + return ERR_PTR(-ERESTARTSYS); + if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) || + !test_bit(AFS_VNODE_DIR_READ, &vnode->flags)) { + ret = afs_read_single(vnode, NULL); + if (ret < 0) { + up_write(&vnode->validate_lock); + return ERR_PTR(ret); + } + set_bit(AFS_VNODE_DIR_READ, &vnode->flags); + } + + up_write(&vnode->validate_lock); good: folio = folioq_folio(vnode->directory, 0);