aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@primarydata.com>2014-05-15 11:56:47 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-05-29 11:11:45 -0400
commit20633f042fd0907300069714b98aaf607a8b5bf8 (patch)
tree33f23c3c0043376a6636367ec64c2962131c7dd9 /fs/nfs
parent67d0338edd71db9a4f406d8778f7c525d31e9f7f (diff)
nfs: page group syncing in write path
Operations that modify state for a whole page must be syncronized across all requests within a page group. In the write path, this is calling end_page_writeback and removing the head request from an inode. Both of these operations should not be called until all requests in a page group have reached the point where they would call them. This patch should have no effect yet since all page groups currently have one request, but will come into play when pg_test functions are modified to split pages into sub-page regions. Signed-off-by: Weston Andros Adamson <dros@primarydata.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/pagelist.c2
-rw-r--r--fs/nfs/write.c32
2 files changed, 22 insertions, 12 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 18ee4e99347e..ceb4424614aa 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -397,6 +397,8 @@ static void nfs_free_request(struct nfs_page *req)
397 WARN_ON_ONCE(test_bit(PG_TEARDOWN, &req->wb_flags)); 397 WARN_ON_ONCE(test_bit(PG_TEARDOWN, &req->wb_flags));
398 WARN_ON_ONCE(test_bit(PG_UNLOCKPAGE, &req->wb_flags)); 398 WARN_ON_ONCE(test_bit(PG_UNLOCKPAGE, &req->wb_flags));
399 WARN_ON_ONCE(test_bit(PG_UPTODATE, &req->wb_flags)); 399 WARN_ON_ONCE(test_bit(PG_UPTODATE, &req->wb_flags));
400 WARN_ON_ONCE(test_bit(PG_WB_END, &req->wb_flags));
401 WARN_ON_ONCE(test_bit(PG_REMOVE, &req->wb_flags));
400 402
401 /* Release struct file and open context */ 403 /* Release struct file and open context */
402 nfs_clear_request(req); 404 nfs_clear_request(req);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index d0f30f12a8b3..5d752766139d 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -201,12 +201,15 @@ static void nfs_set_page_writeback(struct page *page)
201 } 201 }
202} 202}
203 203
204static void nfs_end_page_writeback(struct page *page) 204static void nfs_end_page_writeback(struct nfs_page *req)
205{ 205{
206 struct inode *inode = page_file_mapping(page)->host; 206 struct inode *inode = page_file_mapping(req->wb_page)->host;
207 struct nfs_server *nfss = NFS_SERVER(inode); 207 struct nfs_server *nfss = NFS_SERVER(inode);
208 208
209 end_page_writeback(page); 209 if (!nfs_page_group_sync_on_bit(req, PG_WB_END))
210 return;
211
212 end_page_writeback(req->wb_page);
210 if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) 213 if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH)
211 clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); 214 clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC);
212} 215}
@@ -397,15 +400,20 @@ static void nfs_inode_remove_request(struct nfs_page *req)
397{ 400{
398 struct inode *inode = req->wb_context->dentry->d_inode; 401 struct inode *inode = req->wb_context->dentry->d_inode;
399 struct nfs_inode *nfsi = NFS_I(inode); 402 struct nfs_inode *nfsi = NFS_I(inode);
403 struct nfs_page *head;
400 404
401 spin_lock(&inode->i_lock); 405 if (nfs_page_group_sync_on_bit(req, PG_REMOVE)) {
402 if (likely(!PageSwapCache(req->wb_page))) { 406 head = req->wb_head;
403 set_page_private(req->wb_page, 0); 407
404 ClearPagePrivate(req->wb_page); 408 spin_lock(&inode->i_lock);
405 clear_bit(PG_MAPPED, &req->wb_flags); 409 if (likely(!PageSwapCache(head->wb_page))) {
410 set_page_private(head->wb_page, 0);
411 ClearPagePrivate(head->wb_page);
412 clear_bit(PG_MAPPED, &head->wb_flags);
413 }
414 nfsi->npages--;
415 spin_unlock(&inode->i_lock);
406 } 416 }
407 nfsi->npages--;
408 spin_unlock(&inode->i_lock);
409 nfs_release_request(req); 417 nfs_release_request(req);
410} 418}
411 419
@@ -599,7 +607,7 @@ remove_req:
599 nfs_inode_remove_request(req); 607 nfs_inode_remove_request(req);
600next: 608next:
601 nfs_unlock_request(req); 609 nfs_unlock_request(req);
602 nfs_end_page_writeback(req->wb_page); 610 nfs_end_page_writeback(req);
603 do_destroy = !test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags); 611 do_destroy = !test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags);
604 nfs_release_request(req); 612 nfs_release_request(req);
605 } 613 }
@@ -964,7 +972,7 @@ static void nfs_redirty_request(struct nfs_page *req)
964{ 972{
965 nfs_mark_request_dirty(req); 973 nfs_mark_request_dirty(req);
966 nfs_unlock_request(req); 974 nfs_unlock_request(req);
967 nfs_end_page_writeback(req->wb_page); 975 nfs_end_page_writeback(req);
968 nfs_release_request(req); 976 nfs_release_request(req);
969} 977}
970 978