aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/pagelist.c2
-rw-r--r--fs/nfs/write.c32
-rw-r--r--include/linux/nfs_page.h2
3 files changed, 24 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
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 6385175a127b..7d9096d95d4a 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -31,6 +31,8 @@ enum {
31 PG_TEARDOWN, /* page group sync for destroy */ 31 PG_TEARDOWN, /* page group sync for destroy */
32 PG_UNLOCKPAGE, /* page group sync bit in read path */ 32 PG_UNLOCKPAGE, /* page group sync bit in read path */
33 PG_UPTODATE, /* page group sync bit in read path */ 33 PG_UPTODATE, /* page group sync bit in read path */
34 PG_WB_END, /* page group sync bit in write path */
35 PG_REMOVE, /* page group sync bit in write path */
34}; 36};
35 37
36struct nfs_inode; 38struct nfs_inode;