aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/direct.c2
-rw-r--r--fs/nfs/inode.c69
-rw-r--r--fs/nfs/write.c4
3 files changed, 21 insertions, 54 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 68df803f27ca..d6a30c844de3 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -517,7 +517,7 @@ retry:
517 result = tot_bytes; 517 result = tot_bytes;
518 518
519out: 519out:
520 nfs_end_data_update_defer(inode); 520 nfs_end_data_update(inode);
521 nfs_writedata_free(wdata); 521 nfs_writedata_free(wdata);
522 return result; 522 return result;
523 523
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 6300e05e9463..b2d16758ced8 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1148,27 +1148,6 @@ void nfs_end_data_update(struct inode *inode)
1148} 1148}
1149 1149
1150/** 1150/**
1151 * nfs_end_data_update_defer
1152 * @inode - pointer to inode
1153 * Declare end of the operations that will update file data
1154 * This will defer marking the inode as needing revalidation
1155 * unless there are no other pending updates.
1156 */
1157void nfs_end_data_update_defer(struct inode *inode)
1158{
1159 struct nfs_inode *nfsi = NFS_I(inode);
1160
1161 if (atomic_dec_and_test(&nfsi->data_updates)) {
1162 /* Mark the attribute cache for revalidation */
1163 nfsi->flags |= NFS_INO_INVALID_ATTR;
1164 /* Directories and symlinks: invalidate page cache too */
1165 if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
1166 nfsi->flags |= NFS_INO_INVALID_DATA;
1167 nfsi->cache_change_attribute ++;
1168 }
1169}
1170
1171/**
1172 * nfs_refresh_inode - verify consistency of the inode attribute cache 1151 * nfs_refresh_inode - verify consistency of the inode attribute cache
1173 * @inode - pointer to inode 1152 * @inode - pointer to inode
1174 * @fattr - updated attributes 1153 * @fattr - updated attributes
@@ -1222,8 +1201,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1222 if (!timespec_equal(&inode->i_mtime, &fattr->mtime) 1201 if (!timespec_equal(&inode->i_mtime, &fattr->mtime)
1223 || cur_size != new_isize) 1202 || cur_size != new_isize)
1224 nfsi->flags |= NFS_INO_INVALID_ATTR; 1203 nfsi->flags |= NFS_INO_INVALID_ATTR;
1225 } else if (S_ISREG(inode->i_mode) && new_isize > cur_size) 1204 } else if (new_isize != cur_size && nfsi->npages == 0)
1226 nfsi->flags |= NFS_INO_INVALID_ATTR; 1205 nfsi->flags |= NFS_INO_INVALID_ATTR;
1227 1206
1228 /* Have any file permissions changed? */ 1207 /* Have any file permissions changed? */
1229 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) 1208 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
@@ -1257,10 +1236,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1257static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier) 1236static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier)
1258{ 1237{
1259 struct nfs_inode *nfsi = NFS_I(inode); 1238 struct nfs_inode *nfsi = NFS_I(inode);
1260 __u64 new_size; 1239 loff_t cur_isize, new_isize;
1261 loff_t new_isize;
1262 unsigned int invalid = 0; 1240 unsigned int invalid = 0;
1263 loff_t cur_isize;
1264 int data_unstable; 1241 int data_unstable;
1265 1242
1266 dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", 1243 dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n",
@@ -1293,49 +1270,39 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
1293 /* Are we racing with known updates of the metadata on the server? */ 1270 /* Are we racing with known updates of the metadata on the server? */
1294 data_unstable = ! nfs_verify_change_attribute(inode, verifier); 1271 data_unstable = ! nfs_verify_change_attribute(inode, verifier);
1295 1272
1296 /* Check if the file size agrees */ 1273 /* Check if our cached file size is stale */
1297 new_size = fattr->size;
1298 new_isize = nfs_size_to_loff_t(fattr->size); 1274 new_isize = nfs_size_to_loff_t(fattr->size);
1299 cur_isize = i_size_read(inode); 1275 cur_isize = i_size_read(inode);
1300 if (cur_isize != new_size) { 1276 if (new_isize != cur_isize) {
1301#ifdef NFS_DEBUG_VERBOSE 1277 /* Do we perhaps have any outstanding writes? */
1302 printk(KERN_DEBUG "NFS: isize change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); 1278 if (nfsi->npages == 0) {
1303#endif 1279 /* No, but did we race with nfs_end_data_update()? */
1304 /* 1280 if (verifier == nfsi->cache_change_attribute) {
1305 * If we have pending writebacks, things can get
1306 * messy.
1307 */
1308 if (S_ISREG(inode->i_mode) && data_unstable) {
1309 if (new_isize > cur_isize) {
1310 inode->i_size = new_isize; 1281 inode->i_size = new_isize;
1311 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; 1282 invalid |= NFS_INO_INVALID_DATA;
1312 } 1283 }
1313 } else { 1284 invalid |= NFS_INO_INVALID_ATTR;
1285 } else if (new_isize > cur_isize) {
1314 inode->i_size = new_isize; 1286 inode->i_size = new_isize;
1315 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; 1287 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
1316 } 1288 }
1289 dprintk("NFS: isize change on server for file %s/%ld\n",
1290 inode->i_sb->s_id, inode->i_ino);
1317 } 1291 }
1318 1292
1319 /* 1293 /* Check if the mtime agrees */
1320 * Note: we don't check inode->i_mtime since pipes etc.
1321 * can change this value in VFS without requiring a
1322 * cache revalidation.
1323 */
1324 if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { 1294 if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
1325 memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); 1295 memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
1326#ifdef NFS_DEBUG_VERBOSE 1296 dprintk("NFS: mtime change on server for file %s/%ld\n",
1327 printk(KERN_DEBUG "NFS: mtime change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino); 1297 inode->i_sb->s_id, inode->i_ino);
1328#endif
1329 if (!data_unstable) 1298 if (!data_unstable)
1330 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; 1299 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
1331 } 1300 }
1332 1301
1333 if ((fattr->valid & NFS_ATTR_FATTR_V4) 1302 if ((fattr->valid & NFS_ATTR_FATTR_V4)
1334 && nfsi->change_attr != fattr->change_attr) { 1303 && nfsi->change_attr != fattr->change_attr) {
1335#ifdef NFS_DEBUG_VERBOSE 1304 dprintk("NFS: change_attr change on server for file %s/%ld\n",
1336 printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n",
1337 inode->i_sb->s_id, inode->i_ino); 1305 inode->i_sb->s_id, inode->i_ino);
1338#endif
1339 nfsi->change_attr = fattr->change_attr; 1306 nfsi->change_attr = fattr->change_attr;
1340 if (!data_unstable) 1307 if (!data_unstable)
1341 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; 1308 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 6f7a4af3bc46..c574d551f029 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -220,7 +220,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode,
220 ClearPageError(page); 220 ClearPageError(page);
221 221
222io_error: 222io_error:
223 nfs_end_data_update_defer(inode); 223 nfs_end_data_update(inode);
224 nfs_writedata_free(wdata); 224 nfs_writedata_free(wdata);
225 return written ? written : result; 225 return written ? written : result;
226} 226}
@@ -401,7 +401,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
401 nfsi->npages--; 401 nfsi->npages--;
402 if (!nfsi->npages) { 402 if (!nfsi->npages) {
403 spin_unlock(&nfsi->req_lock); 403 spin_unlock(&nfsi->req_lock);
404 nfs_end_data_update_defer(inode); 404 nfs_end_data_update(inode);
405 iput(inode); 405 iput(inode);
406 } else 406 } else
407 spin_unlock(&nfsi->req_lock); 407 spin_unlock(&nfsi->req_lock);