diff options
-rw-r--r-- | fs/nfs/direct.c | 2 | ||||
-rw-r--r-- | fs/nfs/inode.c | 69 | ||||
-rw-r--r-- | fs/nfs/write.c | 4 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 1 |
4 files changed, 21 insertions, 55 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 | ||
519 | out: | 519 | out: |
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 | */ | ||
1157 | void 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) | |||
1257 | static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier) | 1236 | static 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 | ||
222 | io_error: | 222 | io_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); |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index c90313bfa435..211266c56ce5 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -294,7 +294,6 @@ extern void nfs_begin_attr_update(struct inode *); | |||
294 | extern void nfs_end_attr_update(struct inode *); | 294 | extern void nfs_end_attr_update(struct inode *); |
295 | extern void nfs_begin_data_update(struct inode *); | 295 | extern void nfs_begin_data_update(struct inode *); |
296 | extern void nfs_end_data_update(struct inode *); | 296 | extern void nfs_end_data_update(struct inode *); |
297 | extern void nfs_end_data_update_defer(struct inode *); | ||
298 | extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred); | 297 | extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred); |
299 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); | 298 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); |
300 | extern void put_nfs_open_context(struct nfs_open_context *ctx); | 299 | extern void put_nfs_open_context(struct nfs_open_context *ctx); |