diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/inode.c | 25 | ||||
-rw-r--r-- | fs/nfs/internal.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/proc.c | 4 | ||||
-rw-r--r-- | fs/nfs/write.c | 30 |
6 files changed, 56 insertions, 8 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 299bf7171a4d..ff9a6795da46 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -1491,7 +1491,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1491 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | 1491 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); |
1492 | 1492 | ||
1493 | /** | 1493 | /** |
1494 | * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache | 1494 | * nfs_post_op_update_inode_force_wcc_locked - update the inode attribute cache |
1495 | * @inode - pointer to inode | 1495 | * @inode - pointer to inode |
1496 | * @fattr - updated attributes | 1496 | * @fattr - updated attributes |
1497 | * | 1497 | * |
@@ -1501,11 +1501,10 @@ EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | |||
1501 | * | 1501 | * |
1502 | * This function is mainly designed to be used by the ->write_done() functions. | 1502 | * This function is mainly designed to be used by the ->write_done() functions. |
1503 | */ | 1503 | */ |
1504 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | 1504 | int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr) |
1505 | { | 1505 | { |
1506 | int status; | 1506 | int status; |
1507 | 1507 | ||
1508 | spin_lock(&inode->i_lock); | ||
1509 | /* Don't do a WCC update if these attributes are already stale */ | 1508 | /* Don't do a WCC update if these attributes are already stale */ |
1510 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || | 1509 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || |
1511 | !nfs_inode_attrs_need_update(inode, fattr)) { | 1510 | !nfs_inode_attrs_need_update(inode, fattr)) { |
@@ -1537,6 +1536,26 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa | |||
1537 | } | 1536 | } |
1538 | out_noforce: | 1537 | out_noforce: |
1539 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1538 | status = nfs_post_op_update_inode_locked(inode, fattr); |
1539 | return status; | ||
1540 | } | ||
1541 | |||
1542 | /** | ||
1543 | * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache | ||
1544 | * @inode - pointer to inode | ||
1545 | * @fattr - updated attributes | ||
1546 | * | ||
1547 | * After an operation that has changed the inode metadata, mark the | ||
1548 | * attribute cache as being invalid, then try to update it. Fake up | ||
1549 | * weak cache consistency data, if none exist. | ||
1550 | * | ||
1551 | * This function is mainly designed to be used by the ->write_done() functions. | ||
1552 | */ | ||
1553 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | ||
1554 | { | ||
1555 | int status; | ||
1556 | |||
1557 | spin_lock(&inode->i_lock); | ||
1558 | status = nfs_post_op_update_inode_force_wcc_locked(inode, fattr); | ||
1540 | spin_unlock(&inode->i_lock); | 1559 | spin_unlock(&inode->i_lock); |
1541 | return status; | 1560 | return status; |
1542 | } | 1561 | } |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index b802fb3a2d99..9e6475bc5ba2 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -459,6 +459,7 @@ void nfs_mark_request_commit(struct nfs_page *req, | |||
459 | struct nfs_commit_info *cinfo, | 459 | struct nfs_commit_info *cinfo, |
460 | u32 ds_commit_idx); | 460 | u32 ds_commit_idx); |
461 | int nfs_write_need_commit(struct nfs_pgio_header *); | 461 | int nfs_write_need_commit(struct nfs_pgio_header *); |
462 | void nfs_writeback_update_inode(struct nfs_pgio_header *hdr); | ||
462 | int nfs_generic_commit_list(struct inode *inode, struct list_head *head, | 463 | int nfs_generic_commit_list(struct inode *inode, struct list_head *head, |
463 | int how, struct nfs_commit_info *cinfo); | 464 | int how, struct nfs_commit_info *cinfo); |
464 | void nfs_retry_commit(struct list_head *page_list, | 465 | void nfs_retry_commit(struct list_head *page_list, |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 11109a137c0c..1f11d2533ee4 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -834,7 +834,7 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) | |||
834 | if (nfs3_async_handle_jukebox(task, inode)) | 834 | if (nfs3_async_handle_jukebox(task, inode)) |
835 | return -EAGAIN; | 835 | return -EAGAIN; |
836 | if (task->tk_status >= 0) | 836 | if (task->tk_status >= 0) |
837 | nfs_post_op_update_inode_force_wcc(inode, hdr->res.fattr); | 837 | nfs_writeback_update_inode(hdr); |
838 | return 0; | 838 | return 0; |
839 | } | 839 | } |
840 | 840 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c499e02a58ca..b022e64b76a5 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -4237,7 +4237,7 @@ static int nfs4_write_done_cb(struct rpc_task *task, | |||
4237 | } | 4237 | } |
4238 | if (task->tk_status >= 0) { | 4238 | if (task->tk_status >= 0) { |
4239 | renew_lease(NFS_SERVER(inode), hdr->timestamp); | 4239 | renew_lease(NFS_SERVER(inode), hdr->timestamp); |
4240 | nfs_post_op_update_inode_force_wcc(inode, &hdr->fattr); | 4240 | nfs_writeback_update_inode(hdr); |
4241 | } | 4241 | } |
4242 | return 0; | 4242 | return 0; |
4243 | } | 4243 | } |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 6202bc0f11bb..c63189acd052 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -609,10 +609,8 @@ static int nfs_proc_pgio_rpc_prepare(struct rpc_task *task, | |||
609 | 609 | ||
610 | static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) | 610 | static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) |
611 | { | 611 | { |
612 | struct inode *inode = hdr->inode; | ||
613 | |||
614 | if (task->tk_status >= 0) | 612 | if (task->tk_status >= 0) |
615 | nfs_post_op_update_inode_force_wcc(inode, hdr->res.fattr); | 613 | nfs_writeback_update_inode(hdr); |
616 | return 0; | 614 | return 0; |
617 | } | 615 | } |
618 | 616 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 595d81e354d1..849ed784d6ac 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1377,6 +1377,36 @@ static int nfs_should_remove_suid(const struct inode *inode) | |||
1377 | return 0; | 1377 | return 0; |
1378 | } | 1378 | } |
1379 | 1379 | ||
1380 | static void nfs_writeback_check_extend(struct nfs_pgio_header *hdr, | ||
1381 | struct nfs_fattr *fattr) | ||
1382 | { | ||
1383 | struct nfs_pgio_args *argp = &hdr->args; | ||
1384 | struct nfs_pgio_res *resp = &hdr->res; | ||
1385 | |||
1386 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) | ||
1387 | return; | ||
1388 | if (argp->offset + resp->count != fattr->size) | ||
1389 | return; | ||
1390 | if (nfs_size_to_loff_t(fattr->size) < i_size_read(hdr->inode)) | ||
1391 | return; | ||
1392 | /* Set attribute barrier */ | ||
1393 | nfs_fattr_set_barrier(fattr); | ||
1394 | } | ||
1395 | |||
1396 | void nfs_writeback_update_inode(struct nfs_pgio_header *hdr) | ||
1397 | { | ||
1398 | struct nfs_fattr *fattr = hdr->res.fattr; | ||
1399 | struct inode *inode = hdr->inode; | ||
1400 | |||
1401 | if (fattr == NULL) | ||
1402 | return; | ||
1403 | spin_lock(&inode->i_lock); | ||
1404 | nfs_writeback_check_extend(hdr, fattr); | ||
1405 | nfs_post_op_update_inode_force_wcc_locked(inode, fattr); | ||
1406 | spin_unlock(&inode->i_lock); | ||
1407 | } | ||
1408 | EXPORT_SYMBOL_GPL(nfs_writeback_update_inode); | ||
1409 | |||
1380 | /* | 1410 | /* |
1381 | * This function is called when the WRITE call is complete. | 1411 | * This function is called when the WRITE call is complete. |
1382 | */ | 1412 | */ |