aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c150
1 files changed, 62 insertions, 88 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 175d5d073ccf..12493846a2d3 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -49,6 +49,9 @@ static const struct nfs_rw_ops nfs_rw_write_ops;
49static void nfs_clear_request_commit(struct nfs_page *req); 49static void nfs_clear_request_commit(struct nfs_page *req);
50static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo, 50static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo,
51 struct inode *inode); 51 struct inode *inode);
52static struct nfs_page *
53nfs_page_search_commits_for_head_request_locked(struct nfs_inode *nfsi,
54 struct page *page);
52 55
53static struct kmem_cache *nfs_wdata_cachep; 56static struct kmem_cache *nfs_wdata_cachep;
54static mempool_t *nfs_wdata_mempool; 57static mempool_t *nfs_wdata_mempool;
@@ -95,38 +98,6 @@ static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
95} 98}
96 99
97/* 100/*
98 * nfs_page_search_commits_for_head_request_locked
99 *
100 * Search through commit lists on @inode for the head request for @page.
101 * Must be called while holding the inode (which is cinfo) lock.
102 *
103 * Returns the head request if found, or NULL if not found.
104 */
105static struct nfs_page *
106nfs_page_search_commits_for_head_request_locked(struct nfs_inode *nfsi,
107 struct page *page)
108{
109 struct nfs_page *freq, *t;
110 struct nfs_commit_info cinfo;
111 struct inode *inode = &nfsi->vfs_inode;
112
113 nfs_init_cinfo_from_inode(&cinfo, inode);
114
115 /* search through pnfs commit lists */
116 freq = pnfs_search_commit_reqs(inode, &cinfo, page);
117 if (freq)
118 return freq->wb_head;
119
120 /* Linearly search the commit list for the correct request */
121 list_for_each_entry_safe(freq, t, &cinfo.mds->list, wb_list) {
122 if (freq->wb_page == page)
123 return freq->wb_head;
124 }
125
126 return NULL;
127}
128
129/*
130 * nfs_page_find_head_request_locked - find head request associated with @page 101 * nfs_page_find_head_request_locked - find head request associated with @page
131 * 102 *
132 * must be called while holding the inode lock. 103 * must be called while holding the inode lock.
@@ -271,11 +242,14 @@ static void nfs_mark_uptodate(struct nfs_page *req)
271 242
272static int wb_priority(struct writeback_control *wbc) 243static int wb_priority(struct writeback_control *wbc)
273{ 244{
245 int ret = 0;
274 if (wbc->for_reclaim) 246 if (wbc->for_reclaim)
275 return FLUSH_HIGHPRI | FLUSH_STABLE; 247 return FLUSH_HIGHPRI | FLUSH_STABLE;
248 if (wbc->sync_mode == WB_SYNC_ALL)
249 ret = FLUSH_COND_STABLE;
276 if (wbc->for_kupdate || wbc->for_background) 250 if (wbc->for_kupdate || wbc->for_background)
277 return FLUSH_LOWPRI | FLUSH_COND_STABLE; 251 ret |= FLUSH_LOWPRI;
278 return FLUSH_COND_STABLE; 252 return ret;
279} 253}
280 254
281/* 255/*
@@ -731,6 +705,8 @@ static void nfs_inode_remove_request(struct nfs_page *req)
731 if (likely(!PageSwapCache(head->wb_page))) { 705 if (likely(!PageSwapCache(head->wb_page))) {
732 set_page_private(head->wb_page, 0); 706 set_page_private(head->wb_page, 0);
733 ClearPagePrivate(head->wb_page); 707 ClearPagePrivate(head->wb_page);
708 smp_mb__after_atomic();
709 wake_up_page(head->wb_page, PG_private);
734 clear_bit(PG_MAPPED, &head->wb_flags); 710 clear_bit(PG_MAPPED, &head->wb_flags);
735 } 711 }
736 nfsi->npages--; 712 nfsi->npages--;
@@ -749,7 +725,38 @@ nfs_mark_request_dirty(struct nfs_page *req)
749 __set_page_dirty_nobuffers(req->wb_page); 725 __set_page_dirty_nobuffers(req->wb_page);
750} 726}
751 727
752#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) 728/*
729 * nfs_page_search_commits_for_head_request_locked
730 *
731 * Search through commit lists on @inode for the head request for @page.
732 * Must be called while holding the inode (which is cinfo) lock.
733 *
734 * Returns the head request if found, or NULL if not found.
735 */
736static struct nfs_page *
737nfs_page_search_commits_for_head_request_locked(struct nfs_inode *nfsi,
738 struct page *page)
739{
740 struct nfs_page *freq, *t;
741 struct nfs_commit_info cinfo;
742 struct inode *inode = &nfsi->vfs_inode;
743
744 nfs_init_cinfo_from_inode(&cinfo, inode);
745
746 /* search through pnfs commit lists */
747 freq = pnfs_search_commit_reqs(inode, &cinfo, page);
748 if (freq)
749 return freq->wb_head;
750
751 /* Linearly search the commit list for the correct request */
752 list_for_each_entry_safe(freq, t, &cinfo.mds->list, wb_list) {
753 if (freq->wb_page == page)
754 return freq->wb_head;
755 }
756
757 return NULL;
758}
759
753/** 760/**
754 * nfs_request_add_commit_list - add request to a commit list 761 * nfs_request_add_commit_list - add request to a commit list
755 * @req: pointer to a struct nfs_page 762 * @req: pointer to a struct nfs_page
@@ -867,36 +874,6 @@ int nfs_write_need_commit(struct nfs_pgio_header *hdr)
867 return hdr->verf.committed != NFS_FILE_SYNC; 874 return hdr->verf.committed != NFS_FILE_SYNC;
868} 875}
869 876
870#else
871static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo,
872 struct inode *inode)
873{
874}
875
876void nfs_init_cinfo(struct nfs_commit_info *cinfo,
877 struct inode *inode,
878 struct nfs_direct_req *dreq)
879{
880}
881
882void
883nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
884 struct nfs_commit_info *cinfo)
885{
886}
887
888static void
889nfs_clear_request_commit(struct nfs_page *req)
890{
891}
892
893int nfs_write_need_commit(struct nfs_pgio_header *hdr)
894{
895 return 0;
896}
897
898#endif
899
900static void nfs_write_completion(struct nfs_pgio_header *hdr) 877static void nfs_write_completion(struct nfs_pgio_header *hdr)
901{ 878{
902 struct nfs_commit_info cinfo; 879 struct nfs_commit_info cinfo;
@@ -932,7 +909,6 @@ out:
932 hdr->release(hdr); 909 hdr->release(hdr);
933} 910}
934 911
935#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
936unsigned long 912unsigned long
937nfs_reqs_to_commit(struct nfs_commit_info *cinfo) 913nfs_reqs_to_commit(struct nfs_commit_info *cinfo)
938{ 914{
@@ -989,19 +965,6 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst,
989 return ret; 965 return ret;
990} 966}
991 967
992#else
993unsigned long nfs_reqs_to_commit(struct nfs_commit_info *cinfo)
994{
995 return 0;
996}
997
998int nfs_scan_commit(struct inode *inode, struct list_head *dst,
999 struct nfs_commit_info *cinfo)
1000{
1001 return 0;
1002}
1003#endif
1004
1005/* 968/*
1006 * Search for an existing write request, and attempt to update 969 * Search for an existing write request, and attempt to update
1007 * it to reflect a new dirty region on a given page. 970 * it to reflect a new dirty region on a given page.
@@ -1394,7 +1357,6 @@ static int nfs_writeback_done(struct rpc_task *task,
1394 return status; 1357 return status;
1395 nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, hdr->res.count); 1358 nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, hdr->res.count);
1396 1359
1397#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
1398 if (hdr->res.verf->committed < hdr->args.stable && 1360 if (hdr->res.verf->committed < hdr->args.stable &&
1399 task->tk_status >= 0) { 1361 task->tk_status >= 0) {
1400 /* We tried a write call, but the server did not 1362 /* We tried a write call, but the server did not
@@ -1416,7 +1378,6 @@ static int nfs_writeback_done(struct rpc_task *task,
1416 complain = jiffies + 300 * HZ; 1378 complain = jiffies + 300 * HZ;
1417 } 1379 }
1418 } 1380 }
1419#endif
1420 1381
1421 /* Deal with the suid/sgid bit corner case */ 1382 /* Deal with the suid/sgid bit corner case */
1422 if (nfs_should_remove_suid(inode)) 1383 if (nfs_should_remove_suid(inode))
@@ -1469,7 +1430,6 @@ static void nfs_writeback_result(struct rpc_task *task,
1469} 1430}
1470 1431
1471 1432
1472#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
1473static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) 1433static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait)
1474{ 1434{
1475 int ret; 1435 int ret;
@@ -1538,6 +1498,18 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data,
1538} 1498}
1539EXPORT_SYMBOL_GPL(nfs_initiate_commit); 1499EXPORT_SYMBOL_GPL(nfs_initiate_commit);
1540 1500
1501static loff_t nfs_get_lwb(struct list_head *head)
1502{
1503 loff_t lwb = 0;
1504 struct nfs_page *req;
1505
1506 list_for_each_entry(req, head, wb_list)
1507 if (lwb < (req_offset(req) + req->wb_bytes))
1508 lwb = req_offset(req) + req->wb_bytes;
1509
1510 return lwb;
1511}
1512
1541/* 1513/*
1542 * Set up the argument/result storage required for the RPC call. 1514 * Set up the argument/result storage required for the RPC call.
1543 */ 1515 */
@@ -1557,6 +1529,9 @@ void nfs_init_commit(struct nfs_commit_data *data,
1557 data->inode = inode; 1529 data->inode = inode;
1558 data->cred = first->wb_context->cred; 1530 data->cred = first->wb_context->cred;
1559 data->lseg = lseg; /* reference transferred */ 1531 data->lseg = lseg; /* reference transferred */
1532 /* only set lwb for pnfs commit */
1533 if (lseg)
1534 data->lwb = nfs_get_lwb(&data->pages);
1560 data->mds_ops = &nfs_commit_ops; 1535 data->mds_ops = &nfs_commit_ops;
1561 data->completion_ops = cinfo->completion_ops; 1536 data->completion_ops = cinfo->completion_ops;
1562 data->dreq = cinfo->dreq; 1537 data->dreq = cinfo->dreq;
@@ -1636,6 +1611,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
1636 struct nfs_page *req; 1611 struct nfs_page *req;
1637 int status = data->task.tk_status; 1612 int status = data->task.tk_status;
1638 struct nfs_commit_info cinfo; 1613 struct nfs_commit_info cinfo;
1614 struct nfs_server *nfss;
1639 1615
1640 while (!list_empty(&data->pages)) { 1616 while (!list_empty(&data->pages)) {
1641 req = nfs_list_entry(data->pages.next); 1617 req = nfs_list_entry(data->pages.next);
@@ -1669,6 +1645,10 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
1669 next: 1645 next:
1670 nfs_unlock_and_release_request(req); 1646 nfs_unlock_and_release_request(req);
1671 } 1647 }
1648 nfss = NFS_SERVER(data->inode);
1649 if (atomic_long_read(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH)
1650 clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC);
1651
1672 nfs_init_cinfo(&cinfo, data->inode, data->dreq); 1652 nfs_init_cinfo(&cinfo, data->inode, data->dreq);
1673 if (atomic_dec_and_test(&cinfo.mds->rpcs_out)) 1653 if (atomic_dec_and_test(&cinfo.mds->rpcs_out))
1674 nfs_commit_clear_lock(NFS_I(data->inode)); 1654 nfs_commit_clear_lock(NFS_I(data->inode));
@@ -1778,12 +1758,6 @@ out_mark_dirty:
1778 __mark_inode_dirty(inode, I_DIRTY_DATASYNC); 1758 __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
1779 return ret; 1759 return ret;
1780} 1760}
1781#else
1782static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc)
1783{
1784 return 0;
1785}
1786#endif
1787 1761
1788int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) 1762int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
1789{ 1763{