diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-01-25 15:28:21 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-01-25 15:28:21 -0500 |
commit | 27dc1cd3ad9300f81e1219e5fc305d91d85353f8 (patch) | |
tree | 5f242e02274ce115154e2400b298b82b39302ed2 /fs/nfs | |
parent | b2a2897dc4a59684321de425652061c62a0569d0 (diff) |
NFS: nfs_wcc_update_inode() should set nfsi->attr_gencount
If the call to nfs_wcc_update_inode() results in an attribute update, we
need to ensure that the inode's attr_gencount gets bumped too, otherwise
we are not protected against races with other GETATTR calls.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/inode.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index d8512423ba72..1cc600e77bb4 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -881,9 +881,10 @@ out: | |||
881 | return ret; | 881 | return ret; |
882 | } | 882 | } |
883 | 883 | ||
884 | static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 884 | static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
885 | { | 885 | { |
886 | struct nfs_inode *nfsi = NFS_I(inode); | 886 | struct nfs_inode *nfsi = NFS_I(inode); |
887 | unsigned long ret = 0; | ||
887 | 888 | ||
888 | if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE) | 889 | if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE) |
889 | && (fattr->valid & NFS_ATTR_FATTR_CHANGE) | 890 | && (fattr->valid & NFS_ATTR_FATTR_CHANGE) |
@@ -891,25 +892,32 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
891 | nfsi->change_attr = fattr->change_attr; | 892 | nfsi->change_attr = fattr->change_attr; |
892 | if (S_ISDIR(inode->i_mode)) | 893 | if (S_ISDIR(inode->i_mode)) |
893 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 894 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
895 | ret |= NFS_INO_INVALID_ATTR; | ||
894 | } | 896 | } |
895 | /* If we have atomic WCC data, we may update some attributes */ | 897 | /* If we have atomic WCC data, we may update some attributes */ |
896 | if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME) | 898 | if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME) |
897 | && (fattr->valid & NFS_ATTR_FATTR_CTIME) | 899 | && (fattr->valid & NFS_ATTR_FATTR_CTIME) |
898 | && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) | 900 | && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { |
899 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 901 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
902 | ret |= NFS_INO_INVALID_ATTR; | ||
903 | } | ||
900 | 904 | ||
901 | if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME) | 905 | if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME) |
902 | && (fattr->valid & NFS_ATTR_FATTR_MTIME) | 906 | && (fattr->valid & NFS_ATTR_FATTR_MTIME) |
903 | && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | 907 | && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { |
904 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 908 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
905 | if (S_ISDIR(inode->i_mode)) | 909 | if (S_ISDIR(inode->i_mode)) |
906 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 910 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
911 | ret |= NFS_INO_INVALID_ATTR; | ||
907 | } | 912 | } |
908 | if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) | 913 | if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) |
909 | && (fattr->valid & NFS_ATTR_FATTR_SIZE) | 914 | && (fattr->valid & NFS_ATTR_FATTR_SIZE) |
910 | && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) | 915 | && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) |
911 | && nfsi->npages == 0) | 916 | && nfsi->npages == 0) { |
912 | i_size_write(inode, nfs_size_to_loff_t(fattr->size)); | 917 | i_size_write(inode, nfs_size_to_loff_t(fattr->size)); |
918 | ret |= NFS_INO_INVALID_ATTR; | ||
919 | } | ||
920 | return ret; | ||
913 | } | 921 | } |
914 | 922 | ||
915 | /** | 923 | /** |
@@ -1223,7 +1231,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1223 | | NFS_INO_REVAL_PAGECACHE); | 1231 | | NFS_INO_REVAL_PAGECACHE); |
1224 | 1232 | ||
1225 | /* Do atomic weak cache consistency updates */ | 1233 | /* Do atomic weak cache consistency updates */ |
1226 | nfs_wcc_update_inode(inode, fattr); | 1234 | invalid |= nfs_wcc_update_inode(inode, fattr); |
1227 | 1235 | ||
1228 | /* More cache consistency checks */ | 1236 | /* More cache consistency checks */ |
1229 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) { | 1237 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) { |