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

Commit 4db72b40 authored by Jeff Layton's avatar Jeff Layton Committed by Trond Myklebust
Browse files

nfs: add memory barriers around NFS_INO_INVALID_DATA and NFS_INO_INVALIDATING



If the setting of NFS_INO_INVALIDATING gets reordered to before the
clearing of NFS_INO_INVALID_DATA, then another task may hit a race
window where both appear to be clear, even though the inode's pages are
still in need of invalidation. Fix this by adding the appropriate memory
barriers.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent 17dfeb91
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -274,6 +274,15 @@ out_eof:
	return -EBADCOOKIE;
}

static bool
nfs_readdir_inode_mapping_valid(struct nfs_inode *nfsi)
{
	if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
		return false;
	smp_rmb();
	return !test_bit(NFS_INO_INVALIDATING, &nfsi->flags);
}

static
int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc)
{
@@ -287,9 +296,8 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
			struct nfs_open_dir_context *ctx = desc->file->private_data;

			new_pos = desc->current_index + i;
			if (ctx->attr_gencount != nfsi->attr_gencount
			    || (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
			    || test_bit(NFS_INO_INVALIDATING, &nfsi->flags)) {
			if (ctx->attr_gencount != nfsi->attr_gencount ||
			    !nfs_readdir_inode_mapping_valid(nfsi)) {
				ctx->duped = 0;
				ctx->attr_gencount = nfsi->attr_gencount;
			} else if (new_pos < desc->ctx->pos) {
+1 −0
Original line number Diff line number Diff line
@@ -1050,6 +1050,7 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
	}

	set_bit(NFS_INO_INVALIDATING, bitlock);
	smp_wmb();
	nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
	spin_unlock(&inode->i_lock);
	trace_nfs_invalidate_mapping_enter(inode);
+1 −0
Original line number Diff line number Diff line
@@ -915,6 +915,7 @@ static bool nfs_write_pageuptodate(struct page *page, struct inode *inode)
		goto out;
	if (nfsi->cache_validity & (NFS_INO_INVALID_DATA|NFS_INO_REVAL_PAGECACHE))
		return false;
	smp_rmb();
	if (test_bit(NFS_INO_INVALIDATING, &nfsi->flags))
		return false;
out: