aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/inode.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-31 18:39:07 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-31 18:39:07 -0500
commit8a1f006ad302ea178aefb1f8c67e679c696289e9 (patch)
tree8ba312b39070556d2062a9f90b1a7fa394041d78 /fs/nfs/inode.c
parent14864a52cd8189e8567df8351d9fc7e435133abd (diff)
parenta1800acaf7d1c2bf6d68b9a8f4ab8560cc66555a (diff)
Merge tag 'nfs-for-3.14-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: "Highlights: - Fix several races in nfs_revalidate_mapping - NFSv4.1 slot leakage in the pNFS files driver - Stable fix for a slot leak in nfs40_sequence_done - Don't reject NFSv4 servers that support ACLs with only ALLOW aces" * tag 'nfs-for-3.14-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: nfs: initialize the ACL support bits to zero. NFSv4.1: Cleanup NFSv4.1: Clean up nfs41_sequence_done NFSv4: Fix a slot leak in nfs40_sequence_done NFSv4.1 free slot before resending I/O to MDS nfs: add memory barriers around NFS_INO_INVALID_DATA and NFS_INO_INVALIDATING NFS: Fix races in nfs_revalidate_mapping sunrpc: turn warn_gssd() log message into a dprintk() NFS: fix the handling of NFS_INO_INVALID_DATA flag in nfs_revalidate_mapping nfs: handle servers that support only ALLOW ACE type.
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r--fs/nfs/inode.c51
1 files changed, 43 insertions, 8 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index ea00b34ff071..28a0a3cbd3b7 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -977,11 +977,11 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map
977 if (ret < 0) 977 if (ret < 0)
978 return ret; 978 return ret;
979 } 979 }
980 spin_lock(&inode->i_lock); 980 if (S_ISDIR(inode->i_mode)) {
981 nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; 981 spin_lock(&inode->i_lock);
982 if (S_ISDIR(inode->i_mode))
983 memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); 982 memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
984 spin_unlock(&inode->i_lock); 983 spin_unlock(&inode->i_lock);
984 }
985 nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); 985 nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
986 nfs_fscache_wait_on_invalidate(inode); 986 nfs_fscache_wait_on_invalidate(inode);
987 987
@@ -1008,6 +1008,7 @@ static bool nfs_mapping_need_revalidate_inode(struct inode *inode)
1008int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) 1008int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
1009{ 1009{
1010 struct nfs_inode *nfsi = NFS_I(inode); 1010 struct nfs_inode *nfsi = NFS_I(inode);
1011 unsigned long *bitlock = &nfsi->flags;
1011 int ret = 0; 1012 int ret = 0;
1012 1013
1013 /* swapfiles are not supposed to be shared. */ 1014 /* swapfiles are not supposed to be shared. */
@@ -1019,12 +1020,46 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
1019 if (ret < 0) 1020 if (ret < 0)
1020 goto out; 1021 goto out;
1021 } 1022 }
1022 if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { 1023
1023 trace_nfs_invalidate_mapping_enter(inode); 1024 /*
1024 ret = nfs_invalidate_mapping(inode, mapping); 1025 * We must clear NFS_INO_INVALID_DATA first to ensure that
1025 trace_nfs_invalidate_mapping_exit(inode, ret); 1026 * invalidations that come in while we're shooting down the mappings
1027 * are respected. But, that leaves a race window where one revalidator
1028 * can clear the flag, and then another checks it before the mapping
1029 * gets invalidated. Fix that by serializing access to this part of
1030 * the function.
1031 *
1032 * At the same time, we need to allow other tasks to see whether we
1033 * might be in the middle of invalidating the pages, so we only set
1034 * the bit lock here if it looks like we're going to be doing that.
1035 */
1036 for (;;) {
1037 ret = wait_on_bit(bitlock, NFS_INO_INVALIDATING,
1038 nfs_wait_bit_killable, TASK_KILLABLE);
1039 if (ret)
1040 goto out;
1041 spin_lock(&inode->i_lock);
1042 if (test_bit(NFS_INO_INVALIDATING, bitlock)) {
1043 spin_unlock(&inode->i_lock);
1044 continue;
1045 }
1046 if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
1047 break;
1048 spin_unlock(&inode->i_lock);
1049 goto out;
1026 } 1050 }
1027 1051
1052 set_bit(NFS_INO_INVALIDATING, bitlock);
1053 smp_wmb();
1054 nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
1055 spin_unlock(&inode->i_lock);
1056 trace_nfs_invalidate_mapping_enter(inode);
1057 ret = nfs_invalidate_mapping(inode, mapping);
1058 trace_nfs_invalidate_mapping_exit(inode, ret);
1059
1060 clear_bit_unlock(NFS_INO_INVALIDATING, bitlock);
1061 smp_mb__after_clear_bit();
1062 wake_up_bit(bitlock, NFS_INO_INVALIDATING);
1028out: 1063out:
1029 return ret; 1064 return ret;
1030} 1065}