aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-06-22 13:16:30 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-06-22 16:07:37 -0400
commitfe51beecc55d0b0dce289e4758e7c529a642f63e (patch)
tree9790d77fafbb52b9237ecd65c57002e87f914e12
parent7d52e86274e09fce8ac8f963e3605a84d0a305a7 (diff)
[PATCH] NFS: Ensure that fstat() always returns the correct mtime
Even if the file is open for writes. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/file.c28
-rw-r--r--fs/nfs/inode.c24
-rw-r--r--include/linux/nfs_fs.h1
3 files changed, 39 insertions, 14 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 40436857ed42..5621ba9885f4 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -128,6 +128,21 @@ nfs_file_release(struct inode *inode, struct file *filp)
128} 128}
129 129
130/** 130/**
131 * nfs_revalidate_file - Revalidate the page cache & related metadata
132 * @inode - pointer to inode struct
133 * @file - pointer to file
134 */
135static int nfs_revalidate_file(struct inode *inode, struct file *filp)
136{
137 int retval = 0;
138
139 if ((NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode))
140 retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
141 nfs_revalidate_mapping(inode, filp->f_mapping);
142 return 0;
143}
144
145/**
131 * nfs_revalidate_size - Revalidate the file size 146 * nfs_revalidate_size - Revalidate the file size
132 * @inode - pointer to inode struct 147 * @inode - pointer to inode struct
133 * @file - pointer to struct file 148 * @file - pointer to struct file
@@ -149,7 +164,8 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
149 goto force_reval; 164 goto force_reval;
150 if (nfsi->npages != 0) 165 if (nfsi->npages != 0)
151 return 0; 166 return 0;
152 return nfs_revalidate_inode(server, inode); 167 if (!(NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
168 return 0;
153force_reval: 169force_reval:
154 return __nfs_revalidate_inode(server, inode); 170 return __nfs_revalidate_inode(server, inode);
155} 171}
@@ -210,7 +226,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
210 dentry->d_parent->d_name.name, dentry->d_name.name, 226 dentry->d_parent->d_name.name, dentry->d_name.name,
211 (unsigned long) count, (unsigned long) pos); 227 (unsigned long) count, (unsigned long) pos);
212 228
213 result = nfs_revalidate_inode(NFS_SERVER(inode), inode); 229 result = nfs_revalidate_file(inode, iocb->ki_filp);
214 if (!result) 230 if (!result)
215 result = generic_file_aio_read(iocb, buf, count, pos); 231 result = generic_file_aio_read(iocb, buf, count, pos);
216 return result; 232 return result;
@@ -228,7 +244,7 @@ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
228 dentry->d_parent->d_name.name, dentry->d_name.name, 244 dentry->d_parent->d_name.name, dentry->d_name.name,
229 (unsigned long) count, (unsigned long long) *ppos); 245 (unsigned long) count, (unsigned long long) *ppos);
230 246
231 res = nfs_revalidate_inode(NFS_SERVER(inode), inode); 247 res = nfs_revalidate_file(inode, filp);
232 if (!res) 248 if (!res)
233 res = generic_file_sendfile(filp, ppos, count, actor, target); 249 res = generic_file_sendfile(filp, ppos, count, actor, target);
234 return res; 250 return res;
@@ -244,7 +260,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
244 dfprintk(VFS, "nfs: mmap(%s/%s)\n", 260 dfprintk(VFS, "nfs: mmap(%s/%s)\n",
245 dentry->d_parent->d_name.name, dentry->d_name.name); 261 dentry->d_parent->d_name.name, dentry->d_name.name);
246 262
247 status = nfs_revalidate_inode(NFS_SERVER(inode), inode); 263 status = nfs_revalidate_file(inode, file);
248 if (!status) 264 if (!status)
249 status = generic_file_mmap(file, vma); 265 status = generic_file_mmap(file, vma);
250 return status; 266 return status;
@@ -340,8 +356,8 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
340 result = nfs_revalidate_file_size(inode, iocb->ki_filp); 356 result = nfs_revalidate_file_size(inode, iocb->ki_filp);
341 if (result) 357 if (result)
342 goto out; 358 goto out;
343 } else 359 }
344 nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); 360 nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
345 361
346 result = count; 362 result = count;
347 if (!count) 363 if (!count)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index a3922f4cc0a8..4f545f382ba6 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -620,9 +620,9 @@ nfs_zap_caches(struct inode *inode)
620 620
621 memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); 621 memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
622 if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) 622 if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
623 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; 623 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
624 else 624 else
625 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; 625 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
626} 626}
627 627
628static void nfs_zap_acl_cache(struct inode *inode) 628static void nfs_zap_acl_cache(struct inode *inode)
@@ -1055,6 +1055,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
1055 goto out; 1055 goto out;
1056 } 1056 }
1057 flags = nfsi->flags; 1057 flags = nfsi->flags;
1058 nfsi->flags &= ~NFS_INO_REVAL_PAGECACHE;
1058 /* 1059 /*
1059 * We may need to keep the attributes marked as invalid if 1060 * We may need to keep the attributes marked as invalid if
1060 * we raced with nfs_end_attr_update(). 1061 * we raced with nfs_end_attr_update().
@@ -1187,8 +1188,11 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1187 if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0 1188 if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0
1188 && nfsi->change_attr == fattr->pre_change_attr) 1189 && nfsi->change_attr == fattr->pre_change_attr)
1189 nfsi->change_attr = fattr->change_attr; 1190 nfsi->change_attr = fattr->change_attr;
1190 if (!data_unstable && nfsi->change_attr != fattr->change_attr) 1191 if (nfsi->change_attr != fattr->change_attr) {
1191 nfsi->flags |= NFS_INO_INVALID_ATTR; 1192 nfsi->flags |= NFS_INO_INVALID_ATTR;
1193 if (!data_unstable)
1194 nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
1195 }
1192 } 1196 }
1193 1197
1194 if ((fattr->valid & NFS_ATTR_FATTR) == 0) 1198 if ((fattr->valid & NFS_ATTR_FATTR) == 0)
@@ -1211,12 +1215,16 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1211 } 1215 }
1212 1216
1213 /* Verify a few of the more important attributes */ 1217 /* Verify a few of the more important attributes */
1214 if (!data_unstable) { 1218 if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
1215 if (!timespec_equal(&inode->i_mtime, &fattr->mtime)
1216 || cur_size != new_isize)
1217 nfsi->flags |= NFS_INO_INVALID_ATTR;
1218 } else if (new_isize != cur_size && nfsi->npages == 0)
1219 nfsi->flags |= NFS_INO_INVALID_ATTR; 1219 nfsi->flags |= NFS_INO_INVALID_ATTR;
1220 if (!data_unstable)
1221 nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
1222 }
1223 if (cur_size != new_isize) {
1224 nfsi->flags |= NFS_INO_INVALID_ATTR;
1225 if (nfsi->npages == 0)
1226 nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
1227 }
1220 1228
1221 /* Have any file permissions changed? */ 1229 /* Have any file permissions changed? */
1222 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) 1230 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 443103c13e53..2954e44ed498 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -198,6 +198,7 @@ struct nfs_inode {
198#define NFS_INO_INVALID_ATIME 0x0020 /* cached atime is invalid */ 198#define NFS_INO_INVALID_ATIME 0x0020 /* cached atime is invalid */
199#define NFS_INO_INVALID_ACCESS 0x0040 /* cached access cred invalid */ 199#define NFS_INO_INVALID_ACCESS 0x0040 /* cached access cred invalid */
200#define NFS_INO_INVALID_ACL 0x0080 /* cached acls are invalid */ 200#define NFS_INO_INVALID_ACL 0x0080 /* cached acls are invalid */
201#define NFS_INO_REVAL_PAGECACHE 0x1000 /* must revalidate pagecache */
201 202
202static inline struct nfs_inode *NFS_I(struct inode *inode) 203static inline struct nfs_inode *NFS_I(struct inode *inode)
203{ 204{