Patch "afs: Fix occasional rmdir-then-VNOVNODE with generic/011" has been added to the 6.8-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    afs: Fix occasional rmdir-then-VNOVNODE with generic/011

to the 6.8-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     afs-fix-occasional-rmdir-then-vnovnode-with-generic-.patch
and it can be found in the queue-6.8 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 6cdbf843346615333727d6928ce8fa8dceab5490
Author: David Howells <dhowells@xxxxxxxxxx>
Date:   Wed Mar 13 08:15:03 2024 +0000

    afs: Fix occasional rmdir-then-VNOVNODE with generic/011
    
    [ Upstream commit b74c02a37987d3ea755f96119c527f5e91950592 ]
    
    Sometimes generic/011 causes kafs to follow up an FS.RemoveDir RPC call by
    spending around a second sending a slew of FS.FetchStatus RPC calls to the
    directory just deleted that then abort with VNOVNODE, indicating deletion
    of the target directory.
    
    This seems to stem from userspace attempting to stat the directory or
    something in it:
    
        afs_select_fileserver+0x46d/0xaa2
        afs_wait_for_operation+0x12/0x17e
        afs_fetch_status+0x56/0x75
        afs_validate+0xfb/0x240
        afs_permission+0xef/0x1b0
        inode_permission+0x90/0x139
        link_path_walk.part.0.constprop.0+0x6f/0x2f0
        path_lookupat+0x4c/0xfa
        filename_lookup+0x63/0xd7
        vfs_statx+0x62/0x13f
        vfs_fstatat+0x72/0x8a
    
    The issue appears to be that afs_dir_remove_subdir() marks the callback
    promise as being cancelled by setting the expiry time to AFS_NO_CB_PROMISE
    - which then confuses afs_validate() which sends the FetchStatus to try and
    get a new one before it checks for the AFS_VNODE_DELETED flag which
    indicates that we know the directory got deleted.
    
    Fix this by:
    
     (1) Make afs_check_validity() return true if AFS_VNODE_DELETED is set, and
         then tweak the return from afs_validate() if the DELETED flag is set.
    
     (2) Move the AFS_VNODE_DELETED check in afs_validate() up above the
         expiration check to immediately after we've grabbed the validate_lock.
    
    Fixes: 453924de6212 ("afs: Overhaul invalidation handling to better support RO volumes")
    Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20240313081505.3060173-3-dhowells@xxxxxxxxxx
    Reviewed-by: Marc Dionne <marc.dionne@xxxxxxxxxxxx>
    cc: Marc Dionne <marc.dionne@xxxxxxxxxxxx>
    cc: linux-afs@xxxxxxxxxxxxxxxxxxx
    Signed-off-by: Christian Brauner <brauner@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/afs/validation.c b/fs/afs/validation.c
index 46b37f2cce7d9..32a53fc8dfb26 100644
--- a/fs/afs/validation.c
+++ b/fs/afs/validation.c
@@ -122,6 +122,9 @@ bool afs_check_validity(const struct afs_vnode *vnode)
 	const struct afs_volume *volume = vnode->volume;
 	time64_t deadline = ktime_get_real_seconds() + 10;
 
+	if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
+		return true;
+
 	if (atomic_read(&volume->cb_v_check) != atomic_read(&volume->cb_v_break) ||
 	    atomic64_read(&vnode->cb_expires_at)  <= deadline ||
 	    volume->cb_expires_at <= deadline ||
@@ -389,12 +392,17 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
 	       key_serial(key));
 
 	if (afs_check_validity(vnode))
-		return 0;
+		return test_bit(AFS_VNODE_DELETED, &vnode->flags) ? -ESTALE : 0;
 
 	ret = down_write_killable(&vnode->validate_lock);
 	if (ret < 0)
 		goto error;
 
+	if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
+		ret = -ESTALE;
+		goto error_unlock;
+	}
+
 	/* Validate a volume after the v_break has changed or the volume
 	 * callback expired.  We only want to do this once per volume per
 	 * v_break change.  The actual work will be done when parsing the
@@ -448,12 +456,6 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
 	vnode->cb_ro_snapshot = cb_ro_snapshot;
 	vnode->cb_scrub = cb_scrub;
 
-	if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
-		_debug("file already deleted");
-		ret = -ESTALE;
-		goto error_unlock;
-	}
-
 	/* if the vnode's data version number changed then its contents are
 	 * different */
 	zap |= test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux