aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/inode.c25
-rw-r--r--fs/nfs/internal.h1
-rw-r--r--fs/nfs/nfs3proc.c2
-rw-r--r--fs/nfs/nfs4proc.c2
-rw-r--r--fs/nfs/proc.c4
-rw-r--r--fs/nfs/write.c30
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)
1491EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); 1491EXPORT_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 */
1504int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) 1504int 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 }
1538out_noforce: 1537out_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 */
1553int 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);
461int nfs_write_need_commit(struct nfs_pgio_header *); 461int nfs_write_need_commit(struct nfs_pgio_header *);
462void nfs_writeback_update_inode(struct nfs_pgio_header *hdr);
462int nfs_generic_commit_list(struct inode *inode, struct list_head *head, 463int 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);
464void nfs_retry_commit(struct list_head *page_list, 465void 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
610static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) 610static 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
1380static 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
1396void 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}
1408EXPORT_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 */