Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 17dfeb91 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFS: Fix races in nfs_revalidate_mapping



Commit d529ef83 (NFS: fix the handling
of NFS_INO_INVALID_DATA flag in nfs_revalidate_mapping) introduces
a potential race, since it doesn't test the value of nfsi->cache_validity
and set the bitlock in nfsi->flags atomically.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Cc: Jeff Layton <jlayton@redhat.com>
parent 0ea9de0e
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -1038,23 +1038,23 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
				  nfs_wait_bit_killable, TASK_KILLABLE);
		if (ret)
			goto out;
		if (!(nfsi->cache_validity & NFS_INO_INVALID_DATA))
			goto out;
		if (!test_and_set_bit_lock(NFS_INO_INVALIDATING, bitlock))
		spin_lock(&inode->i_lock);
		if (test_bit(NFS_INO_INVALIDATING, bitlock)) {
			spin_unlock(&inode->i_lock);
			continue;
		}
		if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
			break;
		spin_unlock(&inode->i_lock);
		goto out;
	}

	spin_lock(&inode->i_lock);
	if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
	set_bit(NFS_INO_INVALIDATING, bitlock);
	nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
	spin_unlock(&inode->i_lock);
	trace_nfs_invalidate_mapping_enter(inode);
	ret = nfs_invalidate_mapping(inode, mapping);
	trace_nfs_invalidate_mapping_exit(inode, ret);
	} else {
		/* something raced in and cleared the flag */
		spin_unlock(&inode->i_lock);
	}

	clear_bit_unlock(NFS_INO_INVALIDATING, bitlock);
	smp_mb__after_clear_bit();